package com.mychat.controller;

import com.mychat.annotation.GlobalInterceptor;
import com.mychat.entity.dto.TokenUserInfoDto;
import com.mychat.entity.dto.UserContactSearchResultDto;
import com.mychat.entity.po.UserContact;
import com.mychat.entity.po.UserInfo;
import com.mychat.entity.query.UserContactApplyQuery;
import com.mychat.entity.query.UserContactQuery;
import com.mychat.entity.vo.PaginationResultVO;
import com.mychat.entity.vo.ResponseVO;
import com.mychat.entity.vo.UserInfoVO;
import com.mychat.enums.PageSizeEnum;
import com.mychat.enums.ResponseCodeEnum;
import com.mychat.enums.UserContactStatusEnum;
import com.mychat.enums.UserContactTypeEnum;
import com.mychat.exception.BusinessException;
import com.mychat.service.UserContactApplyService;
import com.mychat.service.UserContactService;
import com.mychat.service.UserInfoService;
import com.mychat.utils.CopyTools;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;

@RestController
@RequestMapping("/contact")
public class UserContactController extends ABaseController{

    Logger logger = LoggerFactory.getLogger(UserContactController.class);

    @Resource
    private UserContactService userContactService;

    @Resource
    private UserInfoService userInfoService;

    @Resource
    private UserContactApplyService userContactApplyService;

    @RequestMapping("/search")
    @GlobalInterceptor
    public ResponseVO search(HttpServletRequest request, @NotEmpty String contactId) {
        TokenUserInfoDto tokenUserInfoDto = getTokenUserInfo(request);
        UserContactSearchResultDto userContactSearchResultDto = this.userContactService.searchContact(tokenUserInfoDto.getUserId(), contactId);
        return getSuccessResponseVO(userContactSearchResultDto);
    }

    @RequestMapping("/applyAdd")
    @GlobalInterceptor
    public ResponseVO applyAdd(HttpServletRequest request, @NotEmpty String contactId, String applyInfo) throws BusinessException {
        TokenUserInfoDto tokenUserInfoDto = getTokenUserInfo(request);
        Integer joinType = userContactApplyService.applyAdd(tokenUserInfoDto, contactId, applyInfo);
        return getSuccessResponseVO(joinType);
    }

    @RequestMapping("/loadApply")
    @GlobalInterceptor
    public ResponseVO loadApply(HttpServletRequest request, Integer pageNo) throws BusinessException {
        TokenUserInfoDto tokenUserInfoDto = getTokenUserInfo(request);

        UserContactApplyQuery applyQuery = new UserContactApplyQuery();
        applyQuery.setOrderBy("last_apply_time desc");
        applyQuery.setReceiveUserId(tokenUserInfoDto.getUserId());
        applyQuery.setPageNo(pageNo);
        applyQuery.setPageSize(PageSizeEnum.size15.getSize());
        applyQuery.setQueryContactInfo(true);
        PaginationResultVO resultVO = userContactApplyService.findListByPage(applyQuery);
        return getSuccessResponseVO(resultVO);
    }

    @RequestMapping("/dealWithApply")
    @GlobalInterceptor
    public ResponseVO dealWithApply(HttpServletRequest request, @NotNull Integer applyId, @NotNull Integer status) throws BusinessException {
        TokenUserInfoDto tokenUserInfoDto = getTokenUserInfo(request);

        this.userContactApplyService.dealWithApply(tokenUserInfoDto.getUserId(), applyId, status);
        return getSuccessResponseVO(null);
    }

    @RequestMapping("/loadContact")
    @GlobalInterceptor
    public ResponseVO loadContact(HttpServletRequest request, @NotNull String contactType) throws BusinessException {
        UserContactTypeEnum userContactTypeEnum = UserContactTypeEnum.getEnumByName(contactType);
        if(null == userContactTypeEnum) {
            throw new BusinessException(ResponseCodeEnum.CODE_600);
        }
        TokenUserInfoDto tokenUserInfoDto = getTokenUserInfo(request);
        UserContactQuery query = new UserContactQuery();
        query.setUserId(tokenUserInfoDto.getUserId());
        query.setContactType(userContactTypeEnum.getType());
        if(userContactTypeEnum == UserContactTypeEnum.USER) {
            logger.info("--------------查询用户----------------");
            query.setQueryContactUserInfo(true);
        } else if(userContactTypeEnum == UserContactTypeEnum.GROUP) {
            logger.info("--------------查询群组----------------");
            query.setQueryGroupInfo(true);
            query.setExcludeMyGroup(true);
        }
        query.setOrderBy("last_update_time desc");
        query.setStatusArray(new Integer[]{
                UserContactStatusEnum.FRIEND.getCode(),
                UserContactStatusEnum.BLACK_BY_FRIEND.getCode(),
                UserContactStatusEnum.DELETED_BY_FRIEND.getCode()
        });
        List<UserContact> contactList = this.userContactService.findListByParam(query);

        return getSuccessResponseVO(contactList);
    }



    @RequestMapping("/getContactInfo")
    @GlobalInterceptor
    public ResponseVO getContactInfo(HttpServletRequest request, @NotNull String contactId) throws BusinessException {
        TokenUserInfoDto tokenUserInfoDto = getTokenUserInfo(request);
        UserInfo userInfo = userInfoService.getUserInfoByUserId(contactId);
        UserInfoVO userInfoVO = CopyTools.copy(userInfo, UserInfoVO.class);
        userInfoVO.setContactStatus(UserContactStatusEnum.NOT_FRIEND.getCode());

        UserContact userContact = this.userContactService.getUserContactByUserIdAndContactId(tokenUserInfoDto.getUserId(), contactId);
        if(null != userContact) {
            userInfoVO.setContactStatus(UserContactStatusEnum.FRIEND.getCode());
        }
        return getSuccessResponseVO(userInfoVO);
    }

    /**
     * 根据联系人ID获取联系人用户信息(一定是加过的好友)
     * 此方法首先验证请求中的联系人ID是否有效，并检查当前用户与该联系人的关系状态
     * 只有当联系人状态为好友、黑名单或被对方删除时，才返回联系人的用户信息
     *
     * @param request HttpServletRequest对象，用于获取请求信息
     * @param contactId 联系人ID，用于查询联系人用户信息，不可为空
     * @return 返回一个ResponseVO对象，包含联系人的用户信息
     * @throws BusinessException 当联系人不存在或状态不符合条件时抛出业务异常
     */
    @RequestMapping("/getContactUserInfo")
    @GlobalInterceptor
    public ResponseVO getContactUserInfo(HttpServletRequest request, @NotNull String contactId) throws BusinessException {
        // 从请求中获取令牌用户信息
        TokenUserInfoDto tokenUserInfoDto = getTokenUserInfo(request);

        // 根据当前用户ID和联系人ID获取用户联系人信息
        UserContact userContact = this.userContactService.getUserContactByUserIdAndContactId(tokenUserInfoDto.getUserId(), contactId);
        // 检查联系人信息是否存在，并验证联系人状态是否为指定的有效状态
        if(null == userContact || !ArrayUtils.contains(new Integer[]{UserContactStatusEnum.FRIEND.getCode(), UserContactStatusEnum.BLACK_BY_FRIEND.getCode(), UserContactStatusEnum.DELETED_BY_FRIEND.getCode()}, userContact.getStatus())) {
            // 如果联系人不存在或状态无效，抛出业务异常
            throw new BusinessException(ResponseCodeEnum.CODE_600);
        }

        // 根据联系人ID获取用户信息
        UserInfo userInfo = userInfoService.getUserInfoByUserId(contactId);
        // 将用户信息复制到用户信息视图对象中
        UserInfoVO userInfoVO = CopyTools.copy(userInfo, UserInfoVO.class);

        // 返回包含用户信息视图对象的成功响应
        return getSuccessResponseVO(userInfoVO);
    }

    @RequestMapping("/delContact")
    @GlobalInterceptor
    public ResponseVO delContact(HttpServletRequest request, @NotNull String contactId) throws BusinessException {
        // 从请求中获取令牌用户信息
        TokenUserInfoDto tokenUserInfoDto = getTokenUserInfo(request);
        this.userContactService.removeUserContact(tokenUserInfoDto.getUserId(), contactId, UserContactStatusEnum.DELETED_BY_ME);
        return getSuccessResponseVO(null);
    }

    @RequestMapping("/addContact2BlackList")
    @GlobalInterceptor
    public ResponseVO addContact2BlackList(HttpServletRequest request, @NotNull String contactId) throws BusinessException {
        // 从请求中获取令牌用户信息
        TokenUserInfoDto tokenUserInfoDto = getTokenUserInfo(request);
        this.userContactService.removeUserContact(tokenUserInfoDto.getUserId(), contactId, UserContactStatusEnum.BLACK_BY_ME);
        return getSuccessResponseVO(null);
    }
}
